#pragma once

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdint.h>

#include "nocopy.hpp"
#include "Comm.h"

const static u_int16_t default_port =  8888 ;
const static std::string default_ip = "0.0.0.0";
const static int defalut_size = 1024;

class UdpServer : public nocopy
{
private:
    u_int16_t _port;
    std::string _ip;
    int _sockfd;

public:
    UdpServer(const u_int16_t port = default_port) : _port(port)
    {
    }

    ~UdpServer()
    {
    }

    void Init()
    {
        // 创建网络套接字文件
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建一个 使用IPV4 UDP链接 的网络套接字

        // 指定网络信息
        struct sockaddr_in local;
        bzero((void *)&local, (size_t)sizeof local);

        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = inet_addr(default_ip.c_str()); // 将 string 的 ip 信息 转换为网络字节序

        // 设置入内核
        int n = bind(_sockfd, (const sockaddr *)&local, (socklen_t)sizeof local);
        if (n != 0)
        {
            // 绑定失败  //计入log
            std::cerr << "bind error! " << std::endl;
            exit(Bind_Err);
        }
    }

    void Start()
    {
        // 服务器开启后一直运行不退出
        char buffer[defalut_size];

        while (true)
        {
            struct sockaddr_in recv_addr;
            bzero((void *)&recv_addr, (size_t)sizeof recv_addr);
            socklen_t len = sizeof recv_addr;
            
            int n = recvfrom(_sockfd, buffer, sizeof buffer - 1, 0, (struct sockaddr *)&recv_addr, &len);
            if (n > 0)
            {
                buffer[n] = 0;
                std::cout << buffer << std::endl;
                std::string ret = "success!";
                sendto(_sockfd,ret.c_str(),ret.size(), 0,(const struct sockaddr*)&recv_addr,len);
            }
        }
    }
};